package com.jianjun.common.util.job;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.CronUtil;
import com.jfinal.aop.Aop;
import com.jianjun.common.constant.Constants;
import com.jianjun.common.constant.ScheduleConstants;
import com.jianjun.common.util.ExceptionUtil;
import com.jianjun.framework.task.RyTask;
import com.jianjun.project.common.model.SysJob;
import com.jianjun.project.common.model.SysJobLog;
import com.jianjun.project.monitor.job.SysJobLogService;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;


/**
 * 定时任务工具类
 *
 * @author source
 *
 */
@UtilityClass
@Slf4j
public class ScheduleUtils {
    private static final ConcurrentHashMap<String, Object> TASK_CACHE = new ConcurrentHashMap<>();

    static {
        TASK_CACHE.put("ryTask", Aop.get(RyTask.class));
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) TASK_CACHE.get(name);
    }


    /**
     * 构建任务键对象
     */
    public static String getJobKey(Long jobId, String jobGroup) {
        return ScheduleConstants.TASK_CLASS_NAME + jobId + "-" + jobGroup;
    }

    /**
     * 创建定时任务
     */
    public static void createScheduleJob(SysJob job) {
        // 构建job信息
        Long jobId = job.getJobId();
        String jobGroup = job.getJobGroup();

        // 暂停任务
        if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) {
            return;
        }

        // 判断是否存在
        if (CronUtil.getScheduler().getTaskTable().getIds().contains(getJobKey(jobId, jobGroup))) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            CronUtil.remove(getJobKey(jobId, jobGroup));
        }

        // 执行调度任务
        CronUtil.schedule(getJobKey(jobId, jobGroup), job.getCronExpression(), () -> executeJob(job));
    }

    public static void executeJob(SysJob job) {
        TimeInterval timer = DateUtil.timer();
        SysJobLog sysJobLog = new SysJobLog();
        sysJobLog.setJobName(job.getJobName());
        sysJobLog.setJobGroup(job.getJobGroup());
        sysJobLog.setInvokeTarget(job.getInvokeTarget());
        try {
            JobInvokeUtil.invokeMethod(job);
            sysJobLog.setStatus(Constants.SUCCESS);
        } catch (Throwable e) {
            sysJobLog.setStatus(Constants.FAIL);
            String errorMsg = StrUtil.sub(ExceptionUtil.getExceptionMessage(e), 0, 2000);
            sysJobLog.setExceptionInfo(errorMsg);
            log.error("任务执行异常", e);
        }
        long interval = timer.interval();
        log.info("InvokeTarget:{},{}ms", job.getInvokeTarget(), interval);
        sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时：" + interval + "毫秒");
        // 写入数据库当中
        Aop.get(SysJobLogService.class).addJobLog(sysJobLog);
    }


    /**
     * 检查包名是否为白名单配置
     *
     * @param invokeTarget 目标字符串
     * @return 结果
     */
    public static boolean whiteList(String invokeTarget) {
        if (JobInvokeUtil.isValidClassName(invokeTarget)) {
            return StrUtil.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
        } else {
            String beanName = JobInvokeUtil.getBeanName(invokeTarget);
            return TASK_CACHE.containsKey(beanName);
        }
    }
}
